package com.reactim.message.converter;

import com.reactim.message.entity.Message;
import com.reactim.message.dto.MessageResponse;
import com.reactim.protocol.MessageProto;
import org.springframework.stereotype.Component;

import java.time.Instant;
import java.time.LocalDateTime;
import java.time.ZoneOffset;
import java.util.stream.Collectors;

/**
 * 消息转换器
 * 在Protobuf消息和实体类之间进行转换
 */
@Component
public class MessageConverter {
    
    /**
     * 将实体类转换为Protobuf消息
     */
    public MessageProto.Message toProtoMessage(Message message) {
        MessageProto.Message.Builder builder = MessageProto.Message.newBuilder()
                .setMessageId(message.getMessageId())
                .setFromUserId(message.getFromUserId())
                .setMessageType(convertMessageType(message.getMessageType()))
                .setStatus(convertMessageStatus(message.getStatus()))
                .setTimestamp(message.getCreatedAt().toEpochSecond(ZoneOffset.UTC))
                .setSequence(message.getSequence());
        
        // 设置接收者信息
        if (message.getToUserId() != null) {
            builder.setToUserId(message.getToUserId());
        }
        if (message.getGroupId() != null) {
            builder.setGroupId(message.getGroupId());
        }
        
        // 转换消息内容
        if (message.getContent() != null) {
            builder.setContent(convertMessageContent(message.getContent()));
        }
        
        // 转换扩展信息
        if (message.getExtra() != null) {
            builder.setExtra(convertMessageExtra(message.getExtra()));
        }
        
        return builder.build();
    }
    
    /**
     * 将Protobuf消息转换为实体类
     */
    public Message fromProtoMessage(MessageProto.Message protoMessage) {
        Message message = new Message();
        message.setMessageId(protoMessage.getMessageId());
        message.setFromUserId(protoMessage.getFromUserId());
        message.setMessageType(convertMessageType(protoMessage.getMessageType()));
        message.setStatus(convertMessageStatus(protoMessage.getStatus()));
        message.setSequence(protoMessage.getSequence());
        
        // 设置时间
        message.setCreatedAt(LocalDateTime.ofInstant(
            Instant.ofEpochSecond(protoMessage.getTimestamp()), ZoneOffset.UTC));
        message.setUpdatedAt(message.getCreatedAt());
        
        // 设置接收者信息
        if (protoMessage.getToUserId() != 0) {
            message.setToUserId(protoMessage.getToUserId());
        }
        if (protoMessage.getGroupId() != 0) {
            message.setGroupId(protoMessage.getGroupId());
        }
        
        // 转换消息内容
        if (protoMessage.hasContent()) {
            message.setContent(convertMessageContent(protoMessage.getContent()));
        }
        
        // 转换扩展信息
        if (protoMessage.hasExtra()) {
            message.setExtra(convertMessageExtra(protoMessage.getExtra()));
        }
        
        return message;
    }
    
    /**
     * 转换消息类型：实体 -> Proto
     */
    private MessageProto.MessageType convertMessageType(Message.MessageType entityType) {
        switch (entityType) {
            case TEXT: return MessageProto.MessageType.TEXT;
            case IMAGE: return MessageProto.MessageType.IMAGE;
            case VOICE: return MessageProto.MessageType.VOICE;
            case VIDEO: return MessageProto.MessageType.VIDEO;
            case FILE: return MessageProto.MessageType.FILE;
            case LOCATION: return MessageProto.MessageType.LOCATION;
            case EMOJI: return MessageProto.MessageType.EMOJI;
            case CONTACT: return MessageProto.MessageType.CONTACT;
            case URL_CARD: return MessageProto.MessageType.URL_CARD;
            case REPLY: return MessageProto.MessageType.REPLY;
            case FORWARD: return MessageProto.MessageType.FORWARD;
            case SYSTEM: return MessageProto.MessageType.SYSTEM;
            default: return MessageProto.MessageType.UNKNOWN;
        }
    }
    

    
    /**
     * 转换消息状态：实体 -> Proto
     */
    private MessageProto.MessageStatus convertMessageStatus(Message.MessageStatus entityStatus) {
        switch (entityStatus) {
            case NORMAL: return MessageProto.MessageStatus.MSG_NORMAL;
            case RECALLED: return MessageProto.MessageStatus.MSG_RECALLED;
            case DELETED: return MessageProto.MessageStatus.MSG_DELETED;
            case EDITED: return MessageProto.MessageStatus.MSG_EDITED;
            default: return MessageProto.MessageStatus.MSG_NORMAL;
        }
    }
    
    /**
     * 转换消息状态：Proto -> 实体
     */
    private Message.MessageStatus convertMessageStatus(MessageProto.MessageStatus protoStatus) {
        switch (protoStatus) {
            case MSG_NORMAL: return Message.MessageStatus.NORMAL;
            case MSG_RECALLED: return Message.MessageStatus.RECALLED;
            case MSG_DELETED: return Message.MessageStatus.DELETED;
            case MSG_EDITED: return Message.MessageStatus.EDITED;
            default: return Message.MessageStatus.NORMAL;
        }
    }
    
    /**
     * 转换消息内容：实体 -> Proto
     */
    private MessageProto.MessageContent convertMessageContent(Message.MessageContent entityContent) {
        MessageProto.MessageContent.Builder builder = MessageProto.MessageContent.newBuilder();
        
        if (entityContent.getText() != null) {
            builder.setText(convertTextContent(entityContent.getText()));
        }
        if (entityContent.getMedia() != null) {
            builder.setMedia(convertMediaContent(entityContent.getMedia()));
        }
        if (entityContent.getLocation() != null) {
            builder.setLocation(convertLocationContent(entityContent.getLocation()));
        }
        if (entityContent.getContact() != null) {
            builder.setContact(convertContactContent(entityContent.getContact()));
        }
        if (entityContent.getUrlCard() != null) {
            builder.setUrlCard(convertUrlCardContent(entityContent.getUrlCard()));
        }
        if (entityContent.getSystem() != null) {
            builder.setSystem(convertSystemContent(entityContent.getSystem()));
        }
        
        return builder.build();
    }
    

    
    /**
     * 转换文本内容：实体 -> Proto
     */
    private MessageProto.TextContent convertTextContent(Message.TextContent entityText) {
        MessageProto.TextContent.Builder builder = MessageProto.TextContent.newBuilder()
                .setText(entityText.getText());
        
        if (entityText.getMentions() != null) {
            builder.addAllMentions(entityText.getMentions());
        }
        if (entityText.getHashtags() != null) {
            builder.addAllHashtags(entityText.getHashtags());
        }
        if (entityText.getFormat() != null) {
            builder.setFormat(convertTextFormat(entityText.getFormat()));
        }
        
        return builder.build();
    }
    
    /**
     * 转换文本内容：Proto -> 实体
     */
    private Message.TextContent convertTextContent(MessageProto.TextContent protoText) {
        Message.TextContent text = new Message.TextContent();
        text.setText(protoText.getText());
        text.setMentions(protoText.getMentionsList());
        text.setHashtags(protoText.getHashtagsList());
        
        if (protoText.hasFormat()) {
            text.setFormat(convertTextFormat(protoText.getFormat()));
        }
        
        return text;
    }
    
    /**
     * 转换文本格式：实体 -> Proto
     */
    private MessageProto.TextFormat convertTextFormat(Message.TextFormat entityFormat) {
        return MessageProto.TextFormat.newBuilder()
                .setBold(entityFormat.getBold() != null ? entityFormat.getBold() : false)
                .setItalic(entityFormat.getItalic() != null ? entityFormat.getItalic() : false)
                .setUnderline(entityFormat.getUnderline() != null ? entityFormat.getUnderline() : false)
                .setColor(entityFormat.getColor() != null ? entityFormat.getColor() : "")
                .build();
    }
    
    /**
     * 转换文本格式：Proto -> 实体
     */
    private Message.TextFormat convertTextFormat(MessageProto.TextFormat protoFormat) {
        Message.TextFormat format = new Message.TextFormat();
        format.setBold(protoFormat.getBold());
        format.setItalic(protoFormat.getItalic());
        format.setUnderline(protoFormat.getUnderline());
        format.setColor(protoFormat.getColor());
        return format;
    }
    
    /**
     * 转换媒体内容：实体 -> Proto
     */
    private MessageProto.MediaContent convertMediaContent(Message.MediaContent entityMedia) {
        MessageProto.MediaContent.Builder builder = MessageProto.MediaContent.newBuilder();
        
        if (entityMedia.getUrl() != null) builder.setUrl(entityMedia.getUrl());
        if (entityMedia.getThumbnailUrl() != null) builder.setThumbnailUrl(entityMedia.getThumbnailUrl());
        if (entityMedia.getFileName() != null) builder.setFileName(entityMedia.getFileName());
        if (entityMedia.getFileSize() != null) builder.setFileSize(entityMedia.getFileSize());
        if (entityMedia.getWidth() != null) builder.setWidth(entityMedia.getWidth());
        if (entityMedia.getHeight() != null) builder.setHeight(entityMedia.getHeight());
        if (entityMedia.getDuration() != null) builder.setDuration(entityMedia.getDuration());
        if (entityMedia.getMimeType() != null) builder.setMimeType(entityMedia.getMimeType());
        if (entityMedia.getHash() != null) builder.setHash(entityMedia.getHash());
        
        return builder.build();
    }
    
    /**
     * 转换媒体内容：Proto -> 实体
     */
    private Message.MediaContent convertMediaContent(MessageProto.MediaContent protoMedia) {
        Message.MediaContent media = new Message.MediaContent();
        media.setUrl(protoMedia.getUrl());
        media.setThumbnailUrl(protoMedia.getThumbnailUrl());
        media.setFileName(protoMedia.getFileName());
        media.setFileSize(protoMedia.getFileSize());
        media.setWidth(protoMedia.getWidth());
        media.setHeight(protoMedia.getHeight());
        media.setDuration(protoMedia.getDuration());
        media.setMimeType(protoMedia.getMimeType());
        media.setHash(protoMedia.getHash());
        return media;
    }
    
    /**
     * 转换位置内容：实体 -> Proto
     */
    private MessageProto.LocationContent convertLocationContent(Message.LocationContent entityLocation) {
        MessageProto.LocationContent.Builder builder = MessageProto.LocationContent.newBuilder()
                .setLatitude(entityLocation.getLatitude())
                .setLongitude(entityLocation.getLongitude());
        
        if (entityLocation.getAddress() != null) builder.setAddress(entityLocation.getAddress());
        if (entityLocation.getPoiName() != null) builder.setPoiName(entityLocation.getPoiName());
        
        return builder.build();
    }
    
    /**
     * 转换位置内容：Proto -> 实体
     */
    private Message.LocationContent convertLocationContent(MessageProto.LocationContent protoLocation) {
        Message.LocationContent location = new Message.LocationContent();
        location.setLatitude(protoLocation.getLatitude());
        location.setLongitude(protoLocation.getLongitude());
        location.setAddress(protoLocation.getAddress());
        location.setPoiName(protoLocation.getPoiName());
        return location;
    }
    
    /**
     * 转换联系人内容：实体 -> Proto
     */
    private MessageProto.ContactContent convertContactContent(Message.ContactContent entityContact) {
        MessageProto.ContactContent.Builder builder = MessageProto.ContactContent.newBuilder()
                .setUserId(entityContact.getUserId());
        
        if (entityContact.getNickname() != null) builder.setNickname(entityContact.getNickname());
        if (entityContact.getAvatarUrl() != null) builder.setAvatarUrl(entityContact.getAvatarUrl());
        if (entityContact.getPhone() != null) builder.setPhone(entityContact.getPhone());
        
        return builder.build();
    }
    
    /**
     * 转换联系人内容：Proto -> 实体
     */
    private Message.ContactContent convertContactContent(MessageProto.ContactContent protoContact) {
        Message.ContactContent contact = new Message.ContactContent();
        contact.setUserId(protoContact.getUserId());
        contact.setNickname(protoContact.getNickname());
        contact.setAvatarUrl(protoContact.getAvatarUrl());
        contact.setPhone(protoContact.getPhone());
        return contact;
    }
    
    /**
     * 转换URL卡片内容：实体 -> Proto
     */
    private MessageProto.UrlCardContent convertUrlCardContent(Message.UrlCardContent entityUrlCard) {
        MessageProto.UrlCardContent.Builder builder = MessageProto.UrlCardContent.newBuilder();
        
        if (entityUrlCard.getUrl() != null) builder.setUrl(entityUrlCard.getUrl());
        if (entityUrlCard.getTitle() != null) builder.setTitle(entityUrlCard.getTitle());
        if (entityUrlCard.getDescription() != null) builder.setDescription(entityUrlCard.getDescription());
        if (entityUrlCard.getImageUrl() != null) builder.setImageUrl(entityUrlCard.getImageUrl());
        if (entityUrlCard.getSiteName() != null) builder.setSiteName(entityUrlCard.getSiteName());
        
        return builder.build();
    }
    
    /**
     * 转换URL卡片内容：Proto -> 实体
     */
    private Message.UrlCardContent convertUrlCardContent(MessageProto.UrlCardContent protoUrlCard) {
        Message.UrlCardContent urlCard = new Message.UrlCardContent();
        urlCard.setUrl(protoUrlCard.getUrl());
        urlCard.setTitle(protoUrlCard.getTitle());
        urlCard.setDescription(protoUrlCard.getDescription());
        urlCard.setImageUrl(protoUrlCard.getImageUrl());
        urlCard.setSiteName(protoUrlCard.getSiteName());
        return urlCard;
    }
    
    /**
     * 转换系统内容：实体 -> Proto
     */
    private MessageProto.SystemContent convertSystemContent(Message.SystemContent entitySystem) {
        MessageProto.SystemContent.Builder builder = MessageProto.SystemContent.newBuilder()
                .setType(convertSystemMessageType(entitySystem.getType()));
        
        if (entitySystem.getContent() != null) builder.setContent(entitySystem.getContent());
        if (entitySystem.getRelatedUsers() != null) builder.addAllRelatedUsers(entitySystem.getRelatedUsers());
        
        return builder.build();
    }
    
    /**
     * 转换系统内容：Proto -> 实体
     */
    private Message.SystemContent convertSystemContent(MessageProto.SystemContent protoSystem) {
        Message.SystemContent system = new Message.SystemContent();
        system.setType(convertSystemMessageType(protoSystem.getType()));
        system.setContent(protoSystem.getContent());
        system.setRelatedUsers(protoSystem.getRelatedUsersList());
        return system;
    }
    
    /**
     * 转换系统消息类型：实体 -> Proto
     */
    private MessageProto.SystemMessageType convertSystemMessageType(Message.SystemMessageType entityType) {
        switch (entityType) {
            case USER_JOIN: return MessageProto.SystemMessageType.USER_JOIN;
            case USER_LEAVE: return MessageProto.SystemMessageType.USER_LEAVE;
            case GROUP_CREATE: return MessageProto.SystemMessageType.GROUP_CREATE;
            case GROUP_DISMISS: return MessageProto.SystemMessageType.GROUP_DISMISS;
            case ADMIN_CHANGE: return MessageProto.SystemMessageType.ADMIN_CHANGE;
            case GROUP_INFO_UPDATE: return MessageProto.SystemMessageType.GROUP_INFO_UPDATE;
            default: return MessageProto.SystemMessageType.USER_JOIN;
        }
    }
    
    /**
     * 转换系统消息类型：Proto -> 实体
     */
    private Message.SystemMessageType convertSystemMessageType(MessageProto.SystemMessageType protoType) {
        switch (protoType) {
            case USER_JOIN: return Message.SystemMessageType.USER_JOIN;
            case USER_LEAVE: return Message.SystemMessageType.USER_LEAVE;
            case GROUP_CREATE: return Message.SystemMessageType.GROUP_CREATE;
            case GROUP_DISMISS: return Message.SystemMessageType.GROUP_DISMISS;
            case ADMIN_CHANGE: return Message.SystemMessageType.ADMIN_CHANGE;
            case GROUP_INFO_UPDATE: return Message.SystemMessageType.GROUP_INFO_UPDATE;
            default: return Message.SystemMessageType.USER_JOIN;
        }
    }
    
    /**
     * 转换扩展信息：实体 -> Proto
     */
    private MessageProto.MessageExtra convertMessageExtra(Message.MessageExtra entityExtra) {
        MessageProto.MessageExtra.Builder builder = MessageProto.MessageExtra.newBuilder();
        
        if (entityExtra.getReplyToMessageId() != null) {
            builder.setReplyToMessageId(entityExtra.getReplyToMessageId());
        }
        
        if (entityExtra.getForwards() != null) {
            builder.addAllForwards(entityExtra.getForwards().stream()
                    .map(this::convertForwardInfo)
                    .collect(Collectors.toList()));
        }
        
        if (entityExtra.getEditInfo() != null) {
            builder.setEditInfo(convertEditInfo(entityExtra.getEditInfo()));
        }
        
        if (entityExtra.getCustomData() != null) {
            builder.putAllCustomData(entityExtra.getCustomData());
        }
        
        return builder.build();
    }
    
    /**
     * 转换扩展信息：Proto -> 实体
     */
    private Message.MessageExtra convertMessageExtra(MessageProto.MessageExtra protoExtra) {
        Message.MessageExtra extra = new Message.MessageExtra();
        extra.setReplyToMessageId(protoExtra.getReplyToMessageId());
        
        if (protoExtra.getForwardsCount() > 0) {
            extra.setForwards(protoExtra.getForwardsList().stream()
                    .map(this::convertForwardInfo)
                    .collect(Collectors.toList()));
        }
        
        if (protoExtra.hasEditInfo()) {
            extra.setEditInfo(convertEditInfo(protoExtra.getEditInfo()));
        }
        
        extra.setCustomData(protoExtra.getCustomDataMap());
        
        return extra;
    }
    
    /**
     * 转换转发信息：实体 -> Proto
     */
    private MessageProto.ForwardInfo convertForwardInfo(Message.ForwardInfo entityForward) {
        MessageProto.ForwardInfo.Builder builder = MessageProto.ForwardInfo.newBuilder()
                .setOriginalMessageId(entityForward.getOriginalMessageId())
                .setOriginalSenderId(entityForward.getOriginalSenderId())
                .setForwardTimestamp(entityForward.getForwardTimestamp().toEpochSecond(ZoneOffset.UTC));
        
        return builder.build();
    }
    
    /**
     * 转换转发信息：Proto -> 实体
     */
    private Message.ForwardInfo convertForwardInfo(MessageProto.ForwardInfo protoForward) {
        Message.ForwardInfo forward = new Message.ForwardInfo();
        forward.setOriginalMessageId(protoForward.getOriginalMessageId());
        forward.setOriginalSenderId(protoForward.getOriginalSenderId());
        forward.setForwardTimestamp(LocalDateTime.ofInstant(
            Instant.ofEpochSecond(protoForward.getForwardTimestamp()), ZoneOffset.UTC));
        return forward;
    }
    
    /**
     * 转换编辑信息：实体 -> Proto
     */
    private MessageProto.EditInfo convertEditInfo(Message.EditInfo entityEdit) {
        MessageProto.EditInfo.Builder builder = MessageProto.EditInfo.newBuilder()
                .setEditTimestamp(entityEdit.getEditTimestamp().toEpochSecond(ZoneOffset.UTC))
                .setEditCount(entityEdit.getEditCount());
        
        if (entityEdit.getOriginalContent() != null) {
            builder.setOriginalContent(entityEdit.getOriginalContent());
        }
        
        return builder.build();
    }
    
    /**
     * 转换编辑信息：Proto -> 实体
     */
    private Message.EditInfo convertEditInfo(MessageProto.EditInfo protoEdit) {
        Message.EditInfo edit = new Message.EditInfo();
        edit.setEditTimestamp(LocalDateTime.ofInstant(
            Instant.ofEpochSecond(protoEdit.getEditTimestamp()), ZoneOffset.UTC));
        edit.setOriginalContent(protoEdit.getOriginalContent());
        edit.setEditCount(protoEdit.getEditCount());
        return edit;
    }
    
    /**
     * 将MessageResponse转换为Message实体
     */
    public Message fromMessageResponse(MessageResponse messageResponse) {
        Message message = new Message();
        message.setMessageId(messageResponse.getMessageId());
        message.setFromUserId(messageResponse.getFromUserId());
        message.setToUserId(messageResponse.getToUserId());
        message.setGroupId(messageResponse.getGroupId());
        message.setConversationId(messageResponse.getConversationId());
        message.setMessageType(messageResponse.getMessageType());
        message.setContent(messageResponse.getContent());
        message.setExtra(messageResponse.getExtra());
        message.setStatus(messageResponse.getStatus());
        message.setCreatedAt(messageResponse.getCreatedAt());
        message.setUpdatedAt(messageResponse.getUpdatedAt());
        message.setSequence(messageResponse.getSequence());
        return message;
    }
    
    /**
     * 转换消息类型：Proto -> 实体（公共方法）
     */
    public Message.MessageType convertMessageType(MessageProto.MessageType protoType) {
        switch (protoType) {
            case TEXT: return Message.MessageType.TEXT;
            case IMAGE: return Message.MessageType.IMAGE;
            case VOICE: return Message.MessageType.VOICE;
            case VIDEO: return Message.MessageType.VIDEO;
            case FILE: return Message.MessageType.FILE;
            case LOCATION: return Message.MessageType.LOCATION;
            case EMOJI: return Message.MessageType.EMOJI;
            case CONTACT: return Message.MessageType.CONTACT;
            case URL_CARD: return Message.MessageType.URL_CARD;
            case REPLY: return Message.MessageType.REPLY;
            case FORWARD: return Message.MessageType.FORWARD;
            case SYSTEM: return Message.MessageType.SYSTEM;
            default: return Message.MessageType.TEXT;
        }
    }
    
    /**
     * 转换消息内容：Proto -> 实体（公共方法）
     */
    public Message.MessageContent convertMessageContent(MessageProto.MessageContent protoContent) {
        Message.MessageContent content = new Message.MessageContent();
        
        switch (protoContent.getContentCase()) {
            case TEXT:
                content.setText(convertTextContent(protoContent.getText()));
                break;
            case MEDIA:
                content.setMedia(convertMediaContent(protoContent.getMedia()));
                break;
            case LOCATION:
                content.setLocation(convertLocationContent(protoContent.getLocation()));
                break;
            case CONTACT:
                content.setContact(convertContactContent(protoContent.getContact()));
                break;
            case URL_CARD:
                content.setUrlCard(convertUrlCardContent(protoContent.getUrlCard()));
                break;
            case SYSTEM:
                content.setSystem(convertSystemContent(protoContent.getSystem()));
                break;
        }
        
        return content;
    }
    
    /**
     * 创建新消息推送通知
     */
    public MessageProto.PushNotification createNewMessagePush(MessageResponse messageResponse) {
        Message message = fromMessageResponse(messageResponse);
        MessageProto.Message protoMessage = toProtoMessage(message);
        
        return MessageProto.PushNotification.newBuilder()
                .setType(MessageProto.PushType.NEW_MESSAGE_PUSH)
                .setNewMessage(protoMessage)
                .setTimestamp(System.currentTimeMillis())
                .build();
    }
    
    /**
     * 创建消息撤回推送通知
     */
    public MessageProto.PushNotification createMessageRecallPush(String messageId, Long fromUserId, String reason) {
        MessageProto.MessageRecallNotification recallNotification = MessageProto.MessageRecallNotification.newBuilder()
                .setMessageId(messageId)
                .setFromUserId(fromUserId)
                .setRecallTimestamp(System.currentTimeMillis())
                .setReason(reason != null ? reason : "")
                .build();
        
        return MessageProto.PushNotification.newBuilder()
                .setType(MessageProto.PushType.MESSAGE_RECALL_PUSH)
                .setRecall(recallNotification)
                .setTimestamp(System.currentTimeMillis())
                .build();
    }
    
    /**
     * 创建已读回执推送通知
     */
    public MessageProto.PushNotification createReadReceiptPush(String messageId, Long readByUserId) {
        MessageProto.ReadReceiptNotification readReceipt = MessageProto.ReadReceiptNotification.newBuilder()
                .setMessageId(messageId)
                .setReadByUserId(readByUserId)
                .setReadTimestamp(System.currentTimeMillis())
                .build();
        
        return MessageProto.PushNotification.newBuilder()
                .setType(MessageProto.PushType.READ_RECEIPT_PUSH)
                .setReadReceipt(readReceipt)
                .setTimestamp(System.currentTimeMillis())
                .build();
    }
    
    /**
     * 创建输入指示器推送通知
     */
    public MessageProto.PushNotification createTypingIndicatorPush(Long fromUserId, String conversationId, boolean isTyping) {
        MessageProto.TypingIndicatorNotification typingNotification = MessageProto.TypingIndicatorNotification.newBuilder()
                .setFromUserId(fromUserId)
                .setConversationId(conversationId)
                .setIsTyping(isTyping)
                .setTimestamp(System.currentTimeMillis())
                .build();
        
        return MessageProto.PushNotification.newBuilder()
                .setType(MessageProto.PushType.TYPING_INDICATOR_PUSH)
                .setTyping(typingNotification)
                .setTimestamp(System.currentTimeMillis())
                .build();
    }
    
    /**
     * 创建用户状态变更推送通知
     */
    public MessageProto.PushNotification createUserStatusPush(Long userId, MessageProto.UserStatus oldStatus, 
                                                              MessageProto.UserStatus newStatus, String deviceInfo) {
        MessageProto.UserStatusNotification statusNotification = MessageProto.UserStatusNotification.newBuilder()
                .setUserId(userId)
                .setOldStatus(oldStatus)
                .setNewStatus(newStatus)
                .setTimestamp(System.currentTimeMillis())
                .setDeviceInfo(deviceInfo != null ? deviceInfo : "")
                .build();
        
        return MessageProto.PushNotification.newBuilder()
                .setType(MessageProto.PushType.USER_STATUS_PUSH)
                .setUserStatus(statusNotification)
                .setTimestamp(System.currentTimeMillis())
                .build();
    }
}